/*


 */

package jas.rpc.http;

import jas.rpc.*;
import jas.rpc.client.*;
import jas.http.request.HttpRequest;
import jas.http.request.HttpRequestFormatter;
import jas.http.response.HttpResponse;
import jas.http.response.ResponseCode;
import java.io.IOException;

/**
 *
 *
 */
public class RpcHttpClientFormatterImpl implements RpcHttpClientFormatter {
    
    private ObjectClientSerializer serializer;
    
    public RpcHttpClientFormatterImpl(ObjectClientSerializer serializer) {
        this.serializer = serializer;
    }

    public HttpRequest writeRequest(String objectId, String methodName, Object[] params, Class[] parameterClasses) {
        
        // Serialize parameters and encode in BASE64
        String[] paramStrings = new String[params.length];
        for (int i=0; i<params.length; i++) {
            paramStrings[i] = serializer.serializeObject(params[i]);
        }
        
        // Construct the URI string
        String uri = objectId + "|" + methodName + "|";
        
        for (int i=0; i<params.length; i++) {
            if (i != 0) {
                uri += "&";
            }
            uri += paramStrings[i];
        }
        
        uri += "|";
        
        for (int i=0; i<parameterClasses.length; i++) {
            if (i != 0) {
                uri += "&";
            }
            uri += parameterClasses[i].getName();
        }
        
        // Create the request
        return HttpRequestFormatter.createGETRequest(uri);
    }
    
    
    private static Exception parseException(String body) {
        int splitAt = body.indexOf(" ");
        if (splitAt == -1)
            return null;
        
        String exceptionName = body.substring(0, splitAt);
        String message = body.substring(splitAt + 1);
        
        if (exceptionName.equals(NonRemoteMethodException.class.getName())) {
            return new NonRemoteMethodException(message);
        }
        return null;
    }

    public RpcResponse parseResponse(HttpResponse response, RpcClient client, StubFactory stubFactory) {
        String body = null;
        try {
            body = response.getBodyAsString();
        } catch (IOException ex) {
            throw new RuntimeException(ex.getMessage());
        }
        
        RpcResponse rpc = new RpcResponse();
        
        if (response.getCode() != ResponseCode.OK) {
            
            Exception ex = parseException(body);
            if (ex == null)
                ex = new RuntimeException("Server reported exception: " + body);
            
            rpc.setException(ex);
            return rpc;
        }
        
        try {
            Object result = serializer.deserializeObject(body, client, stubFactory);
            rpc.setResponse(result);
            return rpc;
            
        } catch (ClassNotFoundException ex) {
            throw new RuntimeException(ex.getMessage());
        }
        
    }

}
